package Concurrency2.Chapter05_Lock;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Instruction：对比内置锁与显式锁的性能差异
 * 10个线程, 累加1万次 理论结果是10万, 测试执行时间
 * 测试结果: 千万数量级以上, 会有性能差异, 显式锁更优.
 * Author：@author MaLi
 */
public class T03_SynchronizedAndLock {
    // Step0, 基础数据准备
    private static int TURNS = 1_000_000; //轮数
    private static int NUMBER = 20; //线程数量
    private static int result = 0; //结果
    private static final Lock lock = new ReentrantLock(); // 显式锁
    private static final Object objLock = new Object(); // 内置锁 - ObjectMonitor(所属线程, 竞争队列, 阻塞队列, 等待队列)

    //用于同步控制 - 让main线程等待自定义线程完成再执行
    private static CountDownLatch countDownLatch = new CountDownLatch(NUMBER);
    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(10);
        long start = System.currentTimeMillis();

        // Step1, 创建指定数量的线程
        for (int i = 0; i < NUMBER; i++) {
            // Step2, 提交具体任务
            pool.submit(() -> {
                for (int j = 0; j < TURNS; j++) {
                    // method1(); //使用显式锁
                    method2();  //使用内置锁
                }
                //同步控制
                countDownLatch.countDown();
            });
        }

        //在这里等待所有任务执行
        countDownLatch.await();
        long end = System.currentTimeMillis();
        // Step3, 输出结果和时间消耗
        System.out.println(result);
        System.out.println("Time wasted: " + (end - start));

        //关闭线程池, 退出app
        pool.shutdownNow();
    }

    private static void method2() {
        synchronized (objLock) {
            result++;
        }
    }

    private static void method1() {
        lock.lock();
        try {
            result++;
        } finally {
            lock.unlock();
        }
    }
}
